#include "stdafx.h"
#include "Win32Window.h"

#include "../app/Timer.h"
#include "../app/Application.h"

namespace WindGE
{
	Win32Window* g_window1 = nullptr;

	LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
	{
		return g_window1->msg_proc(hwnd, msg, wParam, lParam);
	}

	Win32Window::Win32Window()
		: app_inst_(0)
		, hwnd_(0)
		, paused_(false)
		, minimized_(false)
		, maximized_(false)
		, resizing_(false)
		, title_(L"D3D Application")
		, client_width_(1000)
		, client_height_(600)
	{
		g_window1 = this;
	}

	Win32Window::~Win32Window()
	{
	}

	bool Win32Window::init(HINSTANCE appInst, int width, int height)
	{
		app_inst_ = appInst;
		client_width_ = width;
		client_height_ = height;

		WNDCLASS wc;
		wc.style = CS_HREDRAW | CS_VREDRAW;
		wc.lpfnWndProc = MainWndProc;
		wc.cbClsExtra = 0;
		wc.cbWndExtra = 0;
		wc.hInstance = app_inst_;
		wc.hIcon = LoadIcon(0, IDI_APPLICATION);
		wc.hCursor = LoadCursor(0, IDC_ARROW);
		wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
		wc.lpszMenuName = 0;
		wc.lpszClassName = L"D3DWndClassName";

		if (!RegisterClass(&wc))
		{
			MessageBox(0, L"RegisterClass Failed.", 0, 0);
			return false;
		}

		RECT R = { 0, 0, client_width_, client_height_ };
		AdjustWindowRect(&R, WS_OVERLAPPEDWINDOW, false);
		int w = R.right - R.left;
		int h = R.bottom - R.top;

		hwnd_ = CreateWindow(
			L"D3DWndClassName",
			title_.c_str(),
			WS_OVERLAPPEDWINDOW,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			w,
			h,
			0,
			0,
			app_inst_,
			0);
		if (!hwnd_)
		{
			MessageBox(0, L"CreateWindow Failed.", 0, 0);
			return false;
		}

		ShowWindow(hwnd_, SW_SHOW);
		UpdateWindow(hwnd_);
		SetWindowPos(hwnd_, NULL, 50, 50, client_width_, client_height_, NULL);

		return true;
	}

	void Win32Window::resize()
	{
		if (app_) app_->resize((float)client_width_, (float)client_height_);
	}

	int Win32Window::run()
	{
		MSG msg = { 0 };

		Timer::Instance().reset();

		while (msg.message != WM_QUIT)
		{
			if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
			else
			{
				app_->render();
			}
		}
		return (int)msg.wParam;
	}

	LRESULT Win32Window::msg_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
	{
		switch (msg)
		{
		case WM_ACTIVATE:
			if (LOWORD(wParam) == WA_INACTIVE)
			{
				paused_ = true;
				if (app_) app_->pause();
			}
			else
			{
				paused_ = false;
				if (app_) app_->resume();
			}
			return 0;

		case WM_SIZE:
			client_width_ = LOWORD(lParam);
			client_height_ = HIWORD(lParam);

			if (wParam == SIZE_MINIMIZED)
			{
				if (app_) app_->pause();
				paused_ = true;
				minimized_ = true;
				maximized_ = false;
			}
			else if (wParam == SIZE_MAXIMIZED)
			{
				if (app_) app_->resume();
				paused_ = false;
				minimized_ = false;
				maximized_ = true;
				resize();
			}
			else if (wParam == SIZE_RESTORED)
			{
				if (minimized_)
				{
					if (app_) app_->resume();
					paused_ = false;
					minimized_ = false;
					resize();
				}
				else if (maximized_)
				{
					if (app_) app_->resume();
					paused_ = false;
					maximized_ = false;
					resize();
				}
				else if (resizing_)
				{
					//todo
				}
				else
				{
					resize();
				}
			}
			return 0;
		case WM_ENTERSIZEMOVE:
			paused_ = true;
			if (app_) app_->pause();
			resizing_ = true;
			return 0;

		case WM_EXITSIZEMOVE:
			paused_ = false;
			resizing_ = false;
			if (app_) app_->resume();
			resize();
			return 0;

		case WM_DESTROY:
			PostQuitMessage(0);
			return 0;

		case WM_MENUCHAR:
			return MAKELRESULT(0, MNC_CLOSE);

		case WM_GETMINMAXINFO:
			((MINMAXINFO*)lParam)->ptMinTrackSize.x = 200;
			((MINMAXINFO*)lParam)->ptMinTrackSize.y = 200;
			return 0;

		case WM_LBUTTONDOWN:
		case WM_MBUTTONDOWN:
		case WM_RBUTTONDOWN:
			//on_mouse_down(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
			return 0;

		case WM_LBUTTONUP:
		case WM_MBUTTONUP:
		case WM_RBUTTONUP:
			//on_mouse_up(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
			return 0;

		case WM_MOUSEMOVE:
			//on_mouse_move(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
			return 0;
		}
		return DefWindowProc(hwnd, msg, wParam, lParam);
	}
}


